package com.lcc.lynx;

import com.github.pagehelper.PageInterceptor;
import com.lcc.lynx.common.cache.service.CacheService;
import com.lcc.lynx.common.cache.service.impl.RedisCacheServiceImpl;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.boot.autoconfigure.MybatisProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import javax.sql.DataSource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Configuration
@EnableConfigurationProperties(MybatisProperties.class)
@MapperScan("com.lcc.lynx.jdbc.mapper")
public class LynxCodeAutoConfiguration {

    Logger log = LoggerFactory.getLogger(LynxCodeAutoConfiguration.class);

    private String mapperLocations = "classpath:mapper/**/*.xml";

    /**
     * 配置sqlSession工厂
     * @param dataSource
     * @return
     * @throws IOException
     */
    @Bean
    @ConditionalOnMissingBean // 如果容器中不存在 SqlSessionFactoryBean 类型的 Bean，则创建一个
    public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource, MybatisProperties mybatisProperties) throws IOException {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
        configuration.setMapUnderscoreToCamelCase(true);
        configuration.setCallSettersOnNulls(true);
        sqlSessionFactoryBean.setConfiguration(configuration);
        sqlSessionFactoryBean.setDataSource(dataSource);
        sqlSessionFactoryBean.setPlugins(new PageInterceptor());
        sqlSessionFactoryBean.setMapperLocations(getResources(mybatisProperties));
        log.info("[lynx] =================== SqlSessionFactory 初始化完成 ===================");
        return sqlSessionFactoryBean;
    }

    private Resource[] getResources(MybatisProperties mybatisProperties) throws IOException {
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        if(mybatisProperties.getMapperLocations() == null ){
            return resolver.getResources(mapperLocations);
        }else{
            List<Resource> resourceList = new ArrayList<>();
            for (String location : mybatisProperties.getMapperLocations()) {
                Resource[] resources = resolver.getResources(location);
                for (Resource resource : resources) {
                    resourceList.add(resource);
                }
            }
            return resourceList.toArray(new Resource[resourceList.size()]);
        }

    }

    @Bean(name = "redisTemplate")
    @ConditionalOnMissingBean(CacheService.class)
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){

        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        //参照StringRedisTemplate内部实现指定序列化器
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
        return redisTemplate;
    }

    @Bean(name = "redisCacheServiceImpl")
    @ConditionalOnMissingBean(CacheService.class)
    public CacheService cacheService(RedisTemplate<String, Object> redisTemplate){
        log.info("[lynx] =================== RedisCacheImpl 初始化完成 ===================");
        return new RedisCacheServiceImpl(redisTemplate);
    }

}
